#include "8bit.h"
#include "iso2cvt.h"

using namespace std;


static const wchar_t iso2ucs[] = {
	0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
	0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
	0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
	0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
	0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
	0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
	0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
	0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
	0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
	0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
	0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
	0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
};

static const struct cw ucs2iso[] = {
	{0xA0, 0x00A0}, {0xA4, 0x00A4}, {0xA7, 0x00A7}, {0xA8, 0x00A8},
	{0xAD, 0x00AD}, {0xB0, 0x00B0}, {0xB4, 0x00B4}, {0xB8, 0x00B8},
	{0xC1, 0x00C1}, {0xC2, 0x00C2}, {0xC4, 0x00C4}, {0xC7, 0x00C7},
	{0xC9, 0x00C9}, {0xCB, 0x00CB}, {0xCD, 0x00CD}, {0xCE, 0x00CE},
	{0xD3, 0x00D3}, {0xD4, 0x00D4}, {0xD6, 0x00D6}, {0xD7, 0x00D7},
	{0xDA, 0x00DA}, {0xDC, 0x00DC}, {0xDD, 0x00DD}, {0xDF, 0x00DF},
	{0xE1, 0x00E1}, {0xE2, 0x00E2}, {0xE4, 0x00E4}, {0xE7, 0x00E7},
	{0xE9, 0x00E9}, {0xEB, 0x00EB}, {0xED, 0x00ED}, {0xEE, 0x00EE},
	{0xF3, 0x00F3}, {0xF4, 0x00F4}, {0xF6, 0x00F6}, {0xF7, 0x00F7},
	{0xFA, 0x00FA}, {0xFC, 0x00FC}, {0xFD, 0x00FD}, {0xC3, 0x0102},
	{0xE3, 0x0103}, {0xA1, 0x0104}, {0xB1, 0x0105}, {0xC6, 0x0106},
	{0xE6, 0x0107}, {0xC8, 0x010C}, {0xE8, 0x010D}, {0xCF, 0x010E},
	{0xEF, 0x010F}, {0xD0, 0x0110}, {0xF0, 0x0111}, {0xCA, 0x0118},
	{0xEA, 0x0119}, {0xCC, 0x011A}, {0xEC, 0x011B}, {0xC5, 0x0139},
	{0xE5, 0x013A}, {0xA5, 0x013D}, {0xB5, 0x013E}, {0xA3, 0x0141},
	{0xB3, 0x0142}, {0xD1, 0x0143}, {0xF1, 0x0144}, {0xD2, 0x0147},
	{0xF2, 0x0148}, {0xD5, 0x0150}, {0xF5, 0x0151}, {0xC0, 0x0154},
	{0xE0, 0x0155}, {0xD8, 0x0158}, {0xF8, 0x0159}, {0xA6, 0x015A},
	{0xB6, 0x015B}, {0xAA, 0x015E}, {0xBA, 0x015F}, {0xA9, 0x0160},
	{0xB9, 0x0161}, {0xDE, 0x0162}, {0xFE, 0x0163}, {0xAB, 0x0164},
	{0xBB, 0x0165}, {0xD9, 0x016E}, {0xF9, 0x016F}, {0xDB, 0x0170},
	{0xFB, 0x0171}, {0xAC, 0x0179}, {0xBC, 0x017A}, {0xAF, 0x017B},
	{0xBF, 0x017C}, {0xAE, 0x017D}, {0xBE, 0x017E}, {0xB7, 0x02C7},
	{0xA2, 0x02D8}, {0xFF, 0x02D9}, {0xB2, 0x02DB}, {0xBD, 0x02DD}
};


codecvt_base::result iso2cvt::do_in(mbstate_t&, const char* from,
  const char* from_end, const char*& from_next, wchar_t* to,
  wchar_t* to_limit, wchar_t*& to_next) const
{
	return ::do_in(from, from_end, from_next, to, to_limit, to_next, 0xA0,
	  iso2ucs) ? codecvt_base::error : codecvt_base::ok;
}

codecvt_base::result iso2cvt::do_out(mbstate_t&, const wchar_t* from,
  const wchar_t* from_end, const wchar_t*& from_next, char* to,
  char* to_limit, char*& to_next) const
{
	return ::do_out(from, from_end, from_next, to, to_limit, to_next, 0xA0,
	  ucs2iso, sizeof(ucs2iso)) ? codecvt_base::error : codecvt_base::ok;
}

codecvt_base::result iso2cvt::do_unshift(mbstate_t&, char* to, char*,
  char*& to_next) const
{
	to_next = to;

	return codecvt_base::noconv;
}
